/**
 * 
 */
package com.wubo.sec.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wubo.common.util.Assert;
import com.wubo.common.util.ObjectUtils;
import com.wubo.sec.SecurityManager;
import com.wubo.sec.config.LangUtil;
import com.wubo.sec.core.UserData;
import com.wubo.sec.event.UserEvent;
import com.wubo.sec.log.LogHelper;
import com.wubo.sec.model.DeletedUser;
import com.wubo.sec.model.Group;
import com.wubo.sec.model.User;
import com.wubo.sec.service.IUserService;
import com.wubo.sec.util.ArrayUtils;
import com.wubo.sec.util.ObjectDifferenceChecker;
import com.wubo.spring.hibernate.BaseHibernateDao;

/**
 * @author WuBo
 * @CreateDate 2010-8-2
 * @version 1.0.01
 */
@Service
@SuppressWarnings("unchecked")
public class UserService implements IUserService {
	
	private BaseHibernateDao dao;
	
	public BaseHibernateDao getDao() {
		return dao;
	}
	@Autowired
	public void setDao(BaseHibernateDao dao) {
		this.dao = dao;
	}
	
	public List<String[]> listUsername(String username){
		return  dao.find("select u.username,u.truename,u.nickname from User u " +
				"where u.username like '%"+username+"%' or u.truename like '%"+username+"%' or u.nickname like '%"+username+"%'");
	}
	
	public boolean isExist(String username) {
		List<String> list = dao.find("select u.username from User u where u.username = ?", username);
		return list != null && list.size() > 0;
	}
	
	public String create(User u) {
		Assert.notNull(u);
		Assert.hasText(u.getUsername());
		Assert.hasText(u.getPassword());
		
		u.setPassword(SecurityManager.encodePassword(u.getPassword(), u.getUsername()));
		
		java.util.Date now = new java.util.Date();
		String username = SecurityManager.getCurrentUser().getUsername();
		u.setCreateTime(now);
		u.setCreateUser(username);
		u.setUpdateTime(now);
		u.setUpdateUser(username);
		
		if(u.getGroup() == null){
			u.setGroup(Group.DEFAULT_GROUP);
		}
		
		onAdd(u);
		
		String code = (String) dao.save(u);
		
		afterAdd(u);
		
		return code;
	}
	
	private User doGetByUsername(String username){
		Assert.notNull(username);
		
		return dao.get(User.class, username);
	}

	public void delete(User user) {
		onDelete(user);
		
		DeletedUser deletedUser = new DeletedUser();
		deletedUser.setActive(user.isActive());
		deletedUser.setEmail(user.getEmail());
		deletedUser.setExpiredDate(user.getExpiredDate());
		deletedUser.setGroup(user.getGroup());
		deletedUser.setHeadAddr(user.getHeadAddr());
		deletedUser.setLastLoginIP(user.getLastLoginIP());
		deletedUser.setLastLoginTime(user.getLastLoginTime());
		deletedUser.setLocked(user.isLocked());
		deletedUser.setLoginTimes(user.getLoginTimes());
		deletedUser.setNickname(user.getNickname());
		deletedUser.setOwner(user.getOwner());
		deletedUser.setPassword(user.getPassword());
		deletedUser.setTruename(user.getTruename());
		deletedUser.setUsername(user.getUsername());
		deletedUser.setCreateTime(user.getCreateTime());
		deletedUser.setCreateUser(user.getCreateUser());
		deletedUser.setUpdateTime(user.getUpdateTime());
		deletedUser.setUpdateUser(user.getUpdateUser());
		//保存回收站对象
		dao.save(deletedUser);
		//删除用户
		dao.delete(user);
		
		afterDelete(user);
	}
	
	public void lock(String[] usernames, boolean isLock) {
		Assert.notNull(usernames);
		Assert.notEmpty(usernames);
		
		List<String> list = dao.find("select u.username from User u where u.username in ("+ArrayUtils.split(usernames, ",", "'")+") ");
		
		StringBuilder sb = new StringBuilder();
		for(int i=0; i<list.size(); i++){
			if(i>0){sb.append(",");}
			String username = list.get(i);
			sb.append(username);
		}
		
		dao.bulkUpdate("update User u set locked = ? where u.username in ("+ArrayUtils.split(usernames, ",", "'")+")", isLock);

		LogHelper.actionLog(isLock ? LangUtil.get("LockUser") : LangUtil.get("UnLockUser"),
				LangUtil.get("UserCodeDetail", sb.toString()));
	}

	public User get(String username) {
		return getByUsername(username);
	}

	public User getByUsername(String username) {
		Assert.hasText(username);
		
		return getByUsername(username, false);
	}
	
	public User getByUsername(String username, boolean initAuth) {
		dao.setCacheQueries(true);
		
		User u = doGetByUsername(username);
		
		if(u != null){
			if(initAuth) u.getAuthorities();
		}
		
		return u;
	}

	/* (non-Javadoc)
	 * @see com.asc.sf.service.IUserService#update(com.asc.sf.entity.User)
	 */
	public User update(User user) {
		User temp = get(user.getUsername());
		
		User old = temp.clone();
		
		temp.setActive(user.isActive());
		temp.setEmail(user.getEmail());
		temp.setNickname(user.getNickname());
		temp.setTruename(user.getTruename());
		temp.setExpiredDate(user.getExpiredDate());
		
		java.util.Date now = new java.util.Date();
		String username = SecurityManager.getCurrentUser().getUsername();
		temp.setUpdateTime(now);
		temp.setUpdateUser(username);
		
		onUpdate(old, temp);
		
		dao.update(temp);
		
		afterUpdate(old, temp);
		
		return temp;
	}
	
	public User updateSelf(User user) {
		return update(user);
	}
	
	public void onUserLoginSuccess(UserData user, String ip) {
		User u = (User) user;
		u.setLastLoginIP(ip);
		u.setLastLoginTime(new java.util.Date());
		u.setLoginTimes(u.getLoginTimes() + 1);
		
		dao.update(u);
	}
	
	public void onPasswordChange(UserData user, String newpwd) {
		if(user instanceof User){
			User u = (User) user;
			u.setPassword(SecurityManager.encodePassword(newpwd, u.getUsername()));
			dao.update(u);
		}
	}
	
	public List<User> findAll() {
		return dao.find("from User u");
	}
	
	public List<User> find(String filter, Object[] params) {
		return dao.find("from User u "+filter, params);
	}
	
	public List<User> findRunAs(String filter, Object[] params) {
		return find(filter, params);
	}
	
	public long getTotal(String where, Object[] values) {
		Long result = dao.queryForObject("select count(u.username) from User u "+where, values);
		return result;
	}
	
	public List<User> getSplitPage(int start, int limit, String where, Object[] params) {
		return dao.queryForPage(start, limit, "select u from User u "+where, params);
	}
	
	/*----- 发布事件  -----*/
	protected void onAdd(User user){
		SecurityManager.publishEvent(new UserEvent(user, UserEvent.ADD));
	}
	
	protected void onUpdate(User old, User user){
		SecurityManager.publishEvent(new UserEvent(old, user, UserEvent.UPDATE));
	}
	
	protected void onDelete(User user){
		SecurityManager.publishEvent(new UserEvent(user, UserEvent.DELETE));
	}
	
	/*----- 记录日志 -----*/
	protected void afterAdd(User user){
		LogHelper.actionLog(LangUtil.get("CreateUser"), 
				LangUtil.get("UserDetail", ObjectUtils.objToString(user)));
	}
	protected void afterUpdate(User old, User user){
		LogHelper.actionLog(LangUtil.get("UpdateUser"), 
				LangUtil.get("UpdateUserDetail", ObjectDifferenceChecker.check(old, user)));
	}
	protected void afterDelete(User user){
		LogHelper.actionLog(LangUtil.get("DeleteUser"),
				LangUtil.get("UserDetail", ObjectUtils.objToString(user)));
	}
}
